package com.bd.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.bd.util.StringUtil;

@Transactional
public class Dao<T> extends HibernateDaoSupport {

	@PersistenceContext(type = PersistenceContextType.EXTENDED)
	private EntityManager	em;

	@Transactional(propagation = Propagation.NEVER, readOnly = true)
	public T findById(int id) {
		return em.find(getEntityClass(), id);
	}

	@Transactional(propagation = Propagation.NEVER, readOnly = true)
	public List<T> findByParameter(String[] paramNames, String... param) {
		StringBuilder sql = new StringBuilder("FROM " + getTableName() + " where ");
		Query q = em.createQuery(sql.toString());
		for (int i = 0; i < paramNames.length; i++) {
			sql.append(paramNames[i] + "= :" + paramNames[i] + (i == paramNames.length - 1 ? "" : "AND "));
			q.setParameter(paramNames[i], param[i]);
		}
		return q.getResultList();
	}

	@Transactional(propagation = Propagation.NEVER, readOnly = true)
	public List<T> findLike(String column, Object value) {
		Query q = em.createQuery("select u from " + getTableName() + " u WHERE u." + column + " LIKE '%" + value + "%'");
		return (List<T>) q.getResultList();
	}

	@Transactional(propagation = Propagation.NEVER, readOnly = true)
	public List<T> findAll() {
		return em.createQuery("from " + getTableName()).getResultList();
	}

	@Transactional(propagation = Propagation.NEVER, readOnly = true)
	public void save(T entity) {
		em.persist(entity);
	}

	public void saveList(List<T> entity) {
		getHibernateTemplate().saveOrUpdateAll(entity);
	}

	@Transactional(propagation = Propagation.NEVER, readOnly = true)
	public void update(T entity) {
		em.merge(entity);
	}

	@Transactional(propagation = Propagation.NEVER, readOnly = true)
	public void delete(T entity) {
		em.remove(entity);
	}

	public Integer findLastId() {
		Query q = em.createNamedQuery("SELECT max(id) FROM " + getTableName());
		return q.getFirstResult();
	}

	public Class<T> getEntityClass() {
		return null;
	}

	public String getTableName() {
		return StringUtil.formatClassName(getEntityClass());
	}

	/**
	 * @return the em
	 */
	public EntityManager getEm() {
		return em;
	}

	/**
	 * @param em
	 *            the em to set
	 */
	public void setEm(EntityManager em) {
		this.em = em;
	}

	@Autowired
	public void setFactory(SessionFactory factory) {
		setSessionFactory(factory);
	}
}
